// PicturesDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Pictures.h"
#include "PicturesDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPicturesDlg dialog

CPicturesDlg::CPicturesDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CPicturesDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CPicturesDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    m_Logo.LoadBitmap(IDB_LOGO);
    m_SmallBitmap.LoadBitmap(IDB_SMILE);
    m_hIcon = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDR_MAINFRAME));
    m_hIconSmall = (HICON) LoadImage(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
    m_ImgList.Create(IDB_TOOLBAR, 16, 0, RGB(255,0,0));

    m_fSortDirection = FALSE;
}

CPicturesDlg::~CPicturesDlg()
{
    if (m_hIconSmall)
        DestroyIcon(m_hIconSmall);
}

void CPicturesDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CPicturesDlg)
    DDX_Control(pDX, IDC_SFTTREE1, m_Tree);
    //}}AFX_DATA_MAP
}

struct tagColorEntry {
    LPCTSTR lpszName;
    COLORREF color;
} aPropListColors[] = {
    { TEXT("Black"),      RGB(  0,  0,  0),  },
    { TEXT("Blue"),       RGB(  0,  0,255),  },
    { TEXT("Cyan"),       RGB(  0,255,255),  },
    { TEXT("Green"),      RGB(  0,255,  0),  },
    { TEXT("Magenta"),    RGB(255,  0,255),  },
    { TEXT("Red"),        RGB(255,  0,  0),  },
    { TEXT("White"),      RGB(255,255,255),  },
    { TEXT("Yellow"),     RGB(255,255,  0),  },
    { TEXT("Dk Blue"),    RGB(  0,  0,128),  },
    { TEXT("Dk Cyan"),    RGB(  0,128,128),  },
    { TEXT("Dk Green"),   RGB(  0,128,  0),  },
    { TEXT("Dk Magenta"), RGB(128,  0,128),  },
    { TEXT("Dk Red"),     RGB(128,  0,  0),  },
    { TEXT("Dk Yellow"),  RGB(128,128,  0),  },
    { TEXT("Dk Gray"),    RGB(128,128,128),  },
    { TEXT("Lt Gray"),    RGB(192,192,192),  },
    { TEXT("3DDKSHADOW - Dark shadow for 3D elements"), 0x80000000L | COLOR_3DDKSHADOW, },
    { TEXT("3DFACE - Face color for 3D elements"), 0x80000000L | COLOR_3DFACE, },
    { TEXT("3DHILIGHT - Edges facing the light source"), 0x80000000L | COLOR_3DHILIGHT, },
    { TEXT("3DLIGHT - Edges facing the light source"), 0x80000000L | COLOR_3DLIGHT, },
    { TEXT("3DSHADOW - Edges facing away from the light source"), 0x80000000L | COLOR_3DSHADOW, },
    { TEXT("INFOBK - Background color for tooltip controls"), 0x80000000L | COLOR_INFOBK, },
    { TEXT("INFOTEXT - Text color for tooltip controls"), 0x80000000L | COLOR_INFOTEXT, },
    { TEXT("MENUTEXT - Text in menus"), 0x80000000L | COLOR_MENUTEXT, },
    { TEXT("ACTIVEBORDER - Active window border"), 0x80000000L | COLOR_ACTIVEBORDER, },
    { TEXT("ACTIVECAPTION - Active window caption"), 0x80000000L | COLOR_ACTIVECAPTION, },
    { TEXT("APPWORKSPACE - Background color MDI applications"), 0x80000000L | COLOR_APPWORKSPACE, },
    { TEXT("BACKGROUND - Desktop"), 0x80000000L | COLOR_BACKGROUND, },
    { TEXT("BTNFACE - Face shading on push buttons"), 0x80000000L | COLOR_BTNFACE, },
    { TEXT("BTNHILIGHT - Highlight color for buttons"), 0x80000000L | COLOR_BTNHIGHLIGHT, },
    { TEXT("BTNSHADOW - Edge shading on push buttons"), 0x80000000L | COLOR_BTNSHADOW, },
    { TEXT("BTNTEXT - Text on push buttons"), 0x80000000L | COLOR_BTNTEXT, },
    { TEXT("CAPTIONTEXT - Text in caption"), 0x80000000L | COLOR_CAPTIONTEXT, },
    { TEXT("GRAYTEXT - Grayed (disabled) text"), 0x80000000L | COLOR_GRAYTEXT, },
    { TEXT("HIGHLIGHT - Selected Item(s)"), 0x80000000L | COLOR_HIGHLIGHT, },
    { TEXT("HIGHLIGHTTEXT - Text of selected item(s)"), 0x80000000L | COLOR_HIGHLIGHTTEXT, },
    { TEXT("INACTIVEBORDER - Inactive window border"), 0x80000000L | COLOR_INACTIVEBORDER, },
    { TEXT("INACTIVECAPTION - Inactive window caption"), 0x80000000L | COLOR_INACTIVECAPTION, },
    { TEXT("INACTIVECAPTIONTEXT - Inactive caption text color"), 0x80000000L | COLOR_INACTIVECAPTIONTEXT, },
    { TEXT("MENU - Menu background"), 0x80000000L | COLOR_MENU, },
    { TEXT("SCROLLBAR - Scroll bar gray area"), 0x80000000L | COLOR_SCROLLBAR, },
    { TEXT("WINDOW - Window background"), 0x80000000L | COLOR_WINDOW, },
    { TEXT("WINDOWFRAME - Window frame"), 0x80000000L | COLOR_WINDOWFRAME, },
    { TEXT("WINDOWTEXT - Text in windows"), 0x80000000L | COLOR_WINDOWTEXT, },
    { NULL, 0 },
};

BEGIN_MESSAGE_MAP(CPicturesDlg, CDialog)
    //{{AFX_MSG_MAP(CPicturesDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_SIZE()
    ON_WM_TIMER()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPicturesDlg message handlers

BOOL CPicturesDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    CRect rect;
    GetClientRect(&rect);
    m_Tree.MoveWindow(0, 0, rect.Width(), rect.Height());

    m_vTree = m_Tree.GetControlUnknown();
    ASSERT(m_vTree != NULL);

    long ItemIndex = m_vTree->Items->Add("Progress Bars");
    m_vTree->Cell[ItemIndex][1]->Text = _T("SftTree/OCX supports progress bars as cell background (partial or full size).");

    long i = m_vTree->Items->Add("Progress Bar - Full Size");
    m_vTree->Item[i]->Level = 1;
    m_vTree->Cell[i][0]->ProgressMax = 100;  // maximum value 0-100
    m_vTree->Cell[i][0]->ProgressValue = 33; // current value

    i = m_vTree->Items->Add("Progress Bar - Partial");
    m_vTree->Item[i]->Level = 1;
    m_vTree->Cell[i][0]->ProgressColorOrientation = horizontalDefaultOrientationSftTree;
    m_vTree->Cell[i][0]->ProgressStyle = smallDefaultProgressStyleSftTree;
    m_vTree->Cell[i][0]->ProgressMax = 200;  // maximum value 0-200
    m_vTree->Cell[i][0]->ProgressValue = 33; // current value

    i = m_vTree->Items->Add("Progress Bar - with gradient fill");
    m_vTree->Item[i]->Level = 1;
    m_vTree->Cell[i][0]->ProgressColorOrientation = horizontalDefaultOrientationSftTree;
    m_vTree->Cell[i][0]->ProgressStyle = smallDefaultProgressStyleSftTree;
    m_vTree->Cell[i][0]->ProgressColor = RGB(128,128,0);
    m_vTree->Cell[i][0]->ProgressColorEnd = RGB(255,255,0);
    m_vTree->Cell[i][0]->ProgressMax = 50;   // maximum value 0-50
    m_vTree->Cell[i][0]->ProgressValue = 40; // current value

    i = m_vTree->Items->Add("Progress Bar - customizable colors");
    m_vTree->Item[i]->Level = 1;
    m_vTree->Cell[i][0]->ProgressColorOrientation = verticalDefaultOrientationSftTree;
    m_vTree->Cell[i][0]->ProgressStyle = smallDefaultProgressStyleSftTree;
    m_vTree->Cell[i][0]->ProgressColor = RGB(128,128,0);
    m_vTree->Cell[i][0]->ProgressColorEnd = RGB(255,255,0);
    m_vTree->Cell[i][0]->ProgressMax = 150;   // maximum value 0-150
    m_vTree->Cell[i][0]->ProgressValue = 40; // current value
    m_vTree->Cell[i][0]->BackColor = 0x80000000L | COLOR_WINDOW;
    m_vTree->Cell[i][0]->BackColorEnd = RGB(255, 0, 0);
    m_vTree->Cell[i][0]->BackColorOrientation = horizontalDefaultOrientationSftTree;

    ItemIndex = m_vTree->Items->Add("Supported Picture Types");

    m_vTree->Cell[ItemIndex][1]->Text = _T("SftTree/OCX supports numerous image types, such as GDI+, bitmaps, icons, ImageLists and also offers numerous built-in images.");

    // add GDI+ samples

    ItemIndex = m_vTree->Items->Add(_T("GDI+ Images"));
    m_vTree->Item[ItemIndex]->Level = 1;
    m_vTree->Cell[ItemIndex][1]->Text = _T("All GDI+ images are supported, like GIF, JPEG, Exif, PNG, TIFF and device-independent bitmaps (up to 64bpp) with semi-transparent and translucent areas.");

    long i = m_vTree->Items->Add(_T("PNG Sample with alpha-channel for translucent edges"));
    m_vTree->Item[i]->Level = 2;
    UpdateImage(i, IDR_PNG_WARNING, halignSftTreeRight);

    i = m_vTree->Items->Add(_T("Another PNG Sample with alpha-channel for translucent edges"));
    m_vTree->Item[i]->Level = 2;
    UpdateImage(i, IDR_PNG_WORLD, halignSftTreeRight);

    // add bitmap samples

    ItemIndex = m_vTree->Items->Add(_T("Bitmaps"));
    m_vTree->Item[ItemIndex]->Level = 1;
    m_vTree->Cell[ItemIndex][1]->Text = _T("Bitmaps can be of varying sizes and also support Bitmap Transparency, which allows the background to show through the image (in areas selected by the bitmap designer).");

    i = m_vTree->Items->Add(_T("Large Bitmap"));
    m_vTree->Item[i]->Level = 2;
    UpdateBitmap(i, m_Logo, halignSftTreeRight);

    i = m_vTree->Items->Add(_T("Various bitmap sizes"));
    m_vTree->Item[i]->Level = 2;
    UpdateBitmap(i, m_SmallBitmap, halignSftTreeRight);

    // add icon samples
    
    ItemIndex = m_vTree->Items->Add(_T("Icons"));
    m_vTree->Item[ItemIndex]->Level = 1;
    m_vTree->Cell[ItemIndex][1]->Text = _T("The supported icons can be stardard size icons (32x32) or any other size supported by the operating system.");
    
    i = m_vTree->Items->Add(_T("Standard Icon (32x32)"));
    m_vTree->Item[i]->Level = 2;
    UpdateIcon(i, m_hIcon, halignSftTreeRight);

    i = m_vTree->Items->Add(_T("Any other size"));
    m_vTree->Item[i]->Level = 2;
    UpdateIcon(i, m_hIconSmall, halignSftTreeRight);

    // add imagelist samples
    
    ItemIndex = m_vTree->Items->Add(_T("ImageLists"));
    m_vTree->Item[ItemIndex]->Level = 1;
    m_vTree->Cell[ItemIndex][1]->Text = _T("Complete ImageList support simplifies bitmap handling and can avoid the limited resource availability on earlier Windows versions.");

    {
        int c, count = m_ImgList.GetImageCount();
        for (c = 0 ; c < count ; ++c) {
            TCHAR szBuffer[80];
            int i;
            wsprintf(szBuffer, _T("Image %d"), c);
            i = m_vTree->Items->Add(szBuffer);
            m_vTree->Item[i]->Level = 2;
            UpdateImageList(i, (HIMAGELIST) m_ImgList, (short) c, halignSftTreeRight);
        }
    }

    // add color samples
    
    ItemIndex = m_vTree->Items->Add(_T("Color Samples"));
    m_vTree->Item[ItemIndex]->Level = 1;
    m_vTree->Cell[ItemIndex][1]->Text = _T("Using the built-in color sample image, simple color selection can easily be implemented.  Color samples can display all colors available.");
    
    {
        struct tagColorEntry* pc = aPropListColors;
        for ( ; pc->lpszName ; ++pc) {

            i = m_vTree->Items->Add(pc->lpszName);
            m_vTree->Item[i]->Level = 2;
            UpdateColorSample(i, pc->color, halignSftTreeRight);
        }
    }

    // add predefined image samples
    
    ItemIndex = m_vTree->Items->Add(_T("Predefined (Built-in) Pictures"));
    m_vTree->Cell[ItemIndex][1]->Text = _T("Predefined images are available for commonly used items, such as check boxes, radio buttons, sort direction indicators and more...");
    
    ItemIndex = m_vTree->Items->Add(_T("Check Boxes - Honors Windows Themes"));
    m_vTree->Item[ItemIndex]->Level = 1;
    
    AddBuiltinImage(_T("Enabled, Selected Check Box"), sftImageCheckboxYes, 14, 14);
    AddBuiltinImage(_T("Disabled, Selected Check Box"), sftImageCheckboxYesDisabled, 14, 14);
    AddBuiltinImage(_T("Enabled Check Box"), sftImageCheckboxNo, 14, 14);
    AddBuiltinImage(_T("Disabled Check Box"), sftImageCheckboxNoDisabled, 14, 14);
    AddBuiltinImage(_T("Enabled, Unknown Check Box"), sftImageCheckboxUnknown, 14, 14);
    AddBuiltinImage(_T("Disabled, Unknown Check Box"), sftImageCheckboxUnknownDisabled, 14, 14);
    
    ItemIndex = m_vTree->Items->Add(_T("Radio Buttons - Honors Windows Themes"));
    m_vTree->Item[ItemIndex]->Level = 1;
    
    AddBuiltinImage(_T("Enabled, Selected Radio Button"), sftImageRadioButtonYes, 14, 14);
    AddBuiltinImage(_T("Disabled, Selected Radio Button"), sftImageRadioButtonYesDisabled, 14, 14);
    AddBuiltinImage(_T("Enabled Radio Button"), sftImageRadioButtonNo, 14, 14);
    AddBuiltinImage(_T("Disabled Radio Button"), sftImageRadioButtonNoDisabled, 14, 14);

    ItemIndex = m_vTree->Items->Add(_T("Up/Down Buttons - Honors Windows Themes"));
    m_vTree->Item[ItemIndex]->Level = 1;
    
    AddBuiltinImage(_T("Enabled Up Button"), sftImageUp, 14, 14);
    AddBuiltinImage(_T("Disabled Up Button"), sftImageUpDisabled, 14, 14);
    AddBuiltinImage(_T("Enabled Down Button"), sftImageDown, 14, 14);
    AddBuiltinImage(_T("Disabled Down Button"), sftImageDownDisabled, 14, 14);

    ItemIndex = m_vTree->Items->Add(_T("Sort Direction Indicator"));
    m_vTree->Item[ItemIndex]->Level = 1;
    
    AddBuiltinImage(_T("Enabled Ascending Indicator"), sftImageSortAsc, 8, 8);
    AddBuiltinImage(_T("Disabled Ascending Indicator"), sftImageSortAscDisabled, 8, 8);
    AddBuiltinImage(_T("Enabled Descending Indicator"), sftImageSortDesc, 8, 8);
    AddBuiltinImage(_T("Disabled Descending Indicator"), sftImageSortDescDisabled, 8, 8);
   
    
    m_vTree->RowHeaders->MakeOptimal(); // make the row headers optimal
    m_vTree->Column[0]->MakeOptimal(); // make the first column optimal
    m_vTree->Items->RecalcHorizontalExtent(); // update horizontal scroll bar

    m_vTree->Item[0]->Selected = VARIANT_true;
    m_vTree->Items->Current = 0;

    CopyImageFromCurrentItem();

    // Set a timer so we can update our progress bars every once in a while
    SetTimer(TIMERID, 333, NULL);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPicturesDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

void CPicturesDlg::OnTimer( UINT_PTR ID)
{
    // update all cells that have a progress bar by incrementing the progress value
    int items = m_vTree->Items->Count;
    int nCols = m_vTree->ColumnsObj->Count;
    for (int item = 0 ; item < items ; ++item) {
        ISftTreeCellPtr cellObj;
        cellObj = m_vTree->Cell[item][0];
        if (cellObj->ProgressMax > 0)
            cellObj->ProgressValue = (cellObj->ProgressValue + 4) % cellObj->ProgressMax;
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPicturesDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

void CPicturesDlg::OnSize(UINT nType, int cx, int cy) 
{
    CDialog::OnSize(nType, cx, cy);

    if (m_Tree.m_hWnd)
        m_Tree.MoveWindow(0, 0, cx, cy);
}

void CPicturesDlg::PropagateImage(long ItemIndex, ISftPictureObjectPtr Img)
{
    // don't use images that are too large in the other areas
    if (Img->ActualHeight <= 20 && Img->ActualWidth < 20) {
        m_vTree->Item[ItemIndex]->Image = Img;
        m_vTree->Item[ItemIndex]->LabelImage = Img;
        m_vTree->Item[ItemIndex]->RowHeader->Image = Img;
    }
}

void CPicturesDlg::UpdateBitmap(long ItemIndex, const CBitmap& bmp, SftTreeHAlignConstants Align)
{
    ISftTreeCellPtr C = m_vTree->Cell[ItemIndex][0];
    C->Image->PutBitmapHandle((OLE_HANDLE)(HBITMAP) bmp);
    C->ImageHAlign = Align;
    PropagateImage(ItemIndex, C->Image);
}

void CPicturesDlg::UpdateImage(long ItemIndex, int resourceID, SftTreeHAlignConstants Align)
{
    ISftTreeCellPtr C = m_vTree->Cell[ItemIndex][0];
    C->Image->raw_LoadImageFromResource((long) AfxGetApp()->m_hInstance, L"PNG", (LPWSTR)MAKEINTRESOURCE(resourceID));
    C->ImageHAlign = Align;
    PropagateImage(ItemIndex, C->Image);
}

void CPicturesDlg::UpdateIcon(long ItemIndex, HICON hIcon, SftTreeHAlignConstants Align)
{
    ISftTreeCellPtr C = m_vTree->Cell[ItemIndex][0];
    C->Image->PutIconHandle((OLE_HANDLE)hIcon);
    C->ImageHAlign = Align;
    PropagateImage(ItemIndex, C->Image);
}

void CPicturesDlg::UpdateImageList(long ItemIndex, HIMAGELIST hImgList, short iImage, SftTreeHAlignConstants Align)
{
    ISftTreeCellPtr C = m_vTree->Cell[ItemIndex][0];
    C->Image->SetImageListH((OLE_HANDLE)hImgList, iImage);
    C->ImageHAlign = Align;
    PropagateImage(ItemIndex, C->Image);
}

void CPicturesDlg::UpdateColorSample(long ItemIndex, COLORREF Clr, SftTreeHAlignConstants Align)
{
    ISftTreeCellPtr C = m_vTree->Cell[ItemIndex][0];
    C->Image->SetColorSample(Clr, 0x80000000L|COLOR_WINDOWTEXT);
    C->Image->Width = 12;
    C->Image->Height = 12;
    C->ImageHAlign = Align;
    PropagateImage(ItemIndex, C->Image);
}

void CPicturesDlg::AddBuiltinImage(LPCTSTR lpszName, SftPictureImageConstants Appearance, long Width, long Height)
{
    long ItemIndex = m_vTree->Items->Add(lpszName);
    m_vTree->Item[ItemIndex]->Level = 2;

    ISftTreeCellPtr C = m_vTree->Cell[ItemIndex][0];
    C->Image->Appearance = Appearance;
    C->Image->Width = Width;
    C->Image->Height = Height;
    C->ImageHAlign = halignSftTreeRight;
    PropagateImage(ItemIndex, C->Image);
}

void CPicturesDlg::CopyImageFromCurrentItem()
{
    long ItemIndex = m_vTree->Items->Current;
    if (ItemIndex < 0) return;
    
    // don't use images that are too large in the other areas
    ISftPictureObjectPtr pImg = m_vTree->Cell[ItemIndex][0]->Image;
    if (pImg->ActualHeight <= 20 && pImg->ActualWidth <= 20) {
        m_vTree->RowColumnHeader->Image = pImg;
        m_vTree->Header[1]->Image = pImg;
    } else {
        m_vTree->RowColumnHeader->Image->Clear();
        m_vTree->Header[1]->Image->Clear();
    }
}
    
void CPicturesDlg::OnItemClickSftTree1(long ItemIndex, short ColIndex, short AreaType, short Button, short Shift) 
{
    if (AreaType == constSftTreeExpandAll)
        m_vTree->Item[ItemIndex]->Expand(VARIANT_true, VARIANT_true);
    else if (AreaType == constSftTreeColumnHeader && ColIndex == 0)
        SetSortDirection(!m_fSortDirection);
    else if (AreaType == constSftTreeCellGraphic)
        ToggleImage(m_vTree->Cell[ItemIndex][ColIndex]->Image);
    else if (AreaType == constSftTreeItem)
        ToggleImage(m_vTree->Item[ItemIndex]->Image);
    else if (AreaType == constSftTreeLabel)
        ToggleImage(m_vTree->Item[ItemIndex]->LabelImage);
}

void CPicturesDlg::OnItemDblClickSftTree1(long ItemIndex, short ColIndex, short AreaType, short Button, short Shift) 
{
    if (AreaType == constSftTreeColumnRes) {
        m_vTree->Column[ColIndex]->MakeOptimal(); // Make column width optimal
        m_vTree->Items->RecalcHorizontalExtent(); // Update horizontal scroll bar
    } else if (AreaType == constSftTreeColumnHeader && ColIndex == 0)
        SetSortDirection(!m_fSortDirection);
    else if (AreaType == constSftTreeCellGraphic)
        ToggleImage(m_vTree->Cell[ItemIndex][ColIndex]->Image);
}

void CPicturesDlg::OnSelectionChangeSftTree1() 
{
    CopyImageFromCurrentItem();
}

void CPicturesDlg::ShowSortDirection(BOOL fAscending)
{
    if (fAscending)
        m_vTree->Header[0]->Image->Appearance = sftImageSortAsc;
    else
        m_vTree->Header[0]->Image->Appearance = sftImageSortDesc;
    m_fSortDirection = fAscending;
}
    
void CPicturesDlg::SetSortDirection(BOOL fNewDirection)
{
    ShowSortDirection(fNewDirection);
    if (fNewDirection)
        m_vTree->Items->SortDependents(-1, 0, sortSftTreeAscending);
    else
        m_vTree->Items->SortDependents(-1, 0, sortSftTreeDescending);
}

void CPicturesDlg::ToggleImage(ISftPictureObjectPtr pImg)
{
    SftPictureImageConstants Appearance = pImg->Appearance;
    switch (Appearance) {
    case sftImageCheckboxNo:
        pImg->Appearance = sftImageCheckboxYes;
        break;
    case sftImageCheckboxYes:
        pImg->Appearance = sftImageCheckboxNo;
        break;
    case sftImageCheckboxUnknown:
        pImg->Appearance = sftImageCheckboxNo;
        break;
    case sftImageCheckboxNoDisabled:
        pImg->Appearance = sftImageCheckboxYesDisabled;
        break;
    case sftImageCheckboxYesDisabled:
        pImg->Appearance = sftImageCheckboxNoDisabled;
        break;
    case sftImageCheckboxUnknownDisabled:
        pImg->Appearance = sftImageCheckboxNoDisabled;
        break;
    case sftImageRadioButtonNo:
        pImg->Appearance = sftImageRadioButtonYes;
        break;
    case sftImageRadioButtonYes:
        pImg->Appearance = sftImageRadioButtonNo;
        break;
    case sftImageRadioButtonNoDisabled:
        pImg->Appearance = sftImageRadioButtonYesDisabled;
        break;
    case sftImageRadioButtonYesDisabled:
        pImg->Appearance = sftImageRadioButtonNoDisabled;
        break;
    case sftImageUp:
        pImg->Appearance = sftImageDown;
        break;
    case sftImageUpDisabled:
        pImg->Appearance = sftImageDownDisabled;
        break;
    case sftImageDown:
        pImg->Appearance = sftImageUp;
        break;
    case sftImageDownDisabled:
        pImg->Appearance = sftImageUpDisabled;
        break;
    case sftImageSortAsc:
        pImg->Appearance = sftImageSortDesc;
        break;
    case sftImageSortAscDisabled:
        pImg->Appearance = sftImageSortDescDisabled;
        break;
    case sftImageSortDesc:
        pImg->Appearance = sftImageSortAsc;
        break;
    case sftImageSortDescDisabled:
        pImg->Appearance = sftImageSortAscDisabled;
        break;
    default:
        break;
    }
}

BEGIN_EVENTSINK_MAP(CPicturesDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CPicturesDlg)
    ON_EVENT(CPicturesDlg, IDC_SFTTREE1, 4 /* ItemClick */, OnItemClickSftTree1, VTS_I4 VTS_I2 VTS_I2 VTS_I2 VTS_I2)
    ON_EVENT(CPicturesDlg, IDC_SFTTREE1, 5 /* ItemDblClick */, OnItemDblClickSftTree1, VTS_I4 VTS_I2 VTS_I2 VTS_I2 VTS_I2)
    ON_EVENT(CPicturesDlg, IDC_SFTTREE1, 34 /* SelectionChange */, OnSelectionChangeSftTree1, VTS_NONE)
    //}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()